package cn.flant.db.mgr;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;

import cn.flant.db.DB;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public final class C3P0Manager implements ConnectionManager {
	private static Hashtable<String, C3P0Manager> pools = new Hashtable<String, C3P0Manager>();
	private ComboPooledDataSource ds;
	private DB db;
	private String poolKey;

	private C3P0Manager(String poolKey, DB db) {
		this.db = db;
		this.poolKey = poolKey;
		ds = new ComboPooledDataSource();
		try {
			ds.setDriverClass(db.getDriver());
		} catch (PropertyVetoException e) {
		}
		ds.setJdbcUrl(db.getUrl());
		ds.setUser(db.getUsername());
		ds.setPassword(db.getPassword());
		ds.setMaxIdleTime(30);
		ds.setIdleConnectionTestPeriod(30);
		if (db.getTestQuery() != null) {
			ds.setPreferredTestQuery(db.getTestQuery());
		}
		ds.setInitialPoolSize(db.getInitPoolSize());
		ds.setMaxPoolSize(db.getMaxPoolSize());
		ds.setMinPoolSize(db.getMinPoolSize());
		ds.setAcquireIncrement(db.getAcquireIncrement());
		ds.setBreakAfterAcquireFailure(false);
		ds.setAcquireRetryDelay(db.getAcquireRetryDelay());
		ds.setAcquireRetryAttempts(db.getAcquireRetryAttempts());
	}

	public synchronized static ConnectionManager getIntance(DB db) {
		if (db == null) {
			throw new NullPointerException();
		}
		String key = db.getUrl() + "_@_" + db.getUsername();
		C3P0Manager mgr = pools.get(key);
		if (mgr == null) {
			mgr = new C3P0Manager(key, db);
			pools.put(key, mgr);
		}
		return mgr;
	}

	public synchronized void destroy() {
		if (ds != null) {
			try {
				ds.close();
			} catch (Exception e) {
			}
			ds = null;
		}
		if (db != null) {
			pools.remove(poolKey);
			db = null;
		}
	}

	public DB getDbInfo() {
		return db;
	}

	public void closeConnection(Connection conn) {
		DB.close(conn);
	}

	public Connection getConnection() throws SQLException {
		if (ds == null) {
			throw new SQLException("Pool is not available");
		}
		return ds.getConnection();
	}

	@Override
	public boolean isAvailable() {
		return ds != null;
	}
}
